
#include "bootpack.h"


/**初始化PIC 组件*/
void init_pic(void){ 
	io_out8(PIC0_IMR,0xff) ;
	io_out8(PIC1_IMR,0xff);  //禁止全部中断

	io_out8(PIC0_ICW1,0x11);/*边沿触发模式*/
	io_out8(PIC0_ICW2,0x20); /*表示IRQ0 -IRQ7 由 INT20 -INT27接收*/
	io_out8(PIC0_ICW3,0x1<<2);/*PIC1 由IRQ2连接*/
	io_out8(PIC0_ICW4,0x01);/*无缓冲区模式*/

	io_out8(PIC1_ICW1,0x11);/*边沿触发模式*/
	io_out8(PIC1_ICW2,0x28); /*表示IRQ8 -IRQ15 由 INT28 -INT2f接收*/
	io_out8(PIC1_ICW3,2);/*PIC1 由IRQ2连接*/
	io_out8(PIC1_ICW4,0x01);/*无缓冲区模式*/

	io_out8(PIC0_IMR,0xfb) ; //只开启IRQ2位置的中断,其他全禁用 (把该中断权让给PIC1)  11111011
	io_out8(PIC1_IMR,0xff);  //禁止全部中断
	return ;
}

#define PORT_KEYDAT		0x0060

 //keybuf是一个循环队列 
//extern CQUEUE keybuf ,mousebuf;
extern CQUEUE intbuf ;



void handler_int21 (int * esp) {   //键盘监听事件 ，注册到IDT上 
	//BOOTINFO *binfo = (BOOTINFO *) ADR_BOOTINFO ;
	char data;
	
	io_out8(PIC0_OCW2,0x61) ; //表示IRQ1中断已受理 (0x60 + i) ,如果不执行这句，下次的IRQ1中断将被PIC忽略
	data = io_in8(PORT_KEYDAT);
	

	INTDATA dt ;
	dt.data = data ; 
	dt.code = INTDATA_CODE_KEYBOARD ;
	EnQueue (&intbuf,dt); 
	
	return ;
}

void handler_int2c (int * esp) {   //鼠标事件 
	char data ; 
	io_out8(PIC1_OCW2,0x64); //鼠标中断IRQ12
	io_out8(PIC0_OCW2,0x62); //IRQ2位置 (表示PIC1的中断)

	data = io_in8(PORT_KEYDAT); //鼠标使用键盘的控制电路 ，所以访问的端口是一样的
	

	INTDATA dt ;
	dt.data = data ; 
	dt.code = INTDATA_CODE_MOUSE ;
	EnQueue (&intbuf ,dt);
	
	return ;
}

//对于部分机种，PIC初始化时会执行IRQ7中断 ，必须在该中断发生时执行STI，否则系统会出错
void handler_int27 (int * esp){   
	io_out8(PIC0_OCW2, 0x67);  //表示IRQ7中断已受理 (0x60 + i) ,如果不执行这句，下次的IRQ7中断将被PIC忽略
} 


 // 系统保护异常
 int *handler_int0d (int * esp) { 
 	CMD * cmd = (CMD *) (*(int *) 0x0fec) ;
 	TASK * task_n = task_now () ;
 	cmd_putchars (cmd , "\n General Protected Exception\n") ;

 	return &(task_n->tss.esp0) ;
 }